#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

char* getHtml();

int main(){
	int ret = 0;
	int cfd = 0;
       	int sfd = 0;
	struct sockaddr_in s_add, c_add;
	int sin_size;
	unsigned short port = 8080;

	printf("begin!\n");
	//1.建立socket 
	sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == sfd){
		printf("socket build error:%m\n");
		return -1;
	}
	printf("socket build ok!\n");

	//2. 创建服务器地址信息
	memset(&s_add, 0, sizeof(struct sockaddr_in));
	s_add.sin_family = AF_INET;
	s_add.sin_addr.s_addr = INADDR_ANY;/*这里使用本机所有地址*/
	s_add.sin_port = htons(port);
	printf("server address build ok!\n");

	//3. 绑定服务器地址
	ret = bind(sfd, (struct sockaddr*)(&s_add), sizeof(struct sockaddr));
	if(-1 == ret){
		printf("bind error:%m\n");
		return -1;
	}
	printf("bind ok!\n");

	//4. 开始监听
	ret = listen(sfd, 5);
	if(-1 == ret){
		printf("listen error:%m\n");
		return -1;
	}
	printf("listen ok!\n");

	//5. 开始接受客户端请求
	while(1){
		cfd = accept(sfd, NULL, NULL);
		if(-1 == cfd){
			printf("accept error:%m\n");
			return -1;
		}
		printf("accept ok!\n");

		int recv_size = 1024;
		char* buffer = (char*)malloc(recv_size);
		ret = read(cfd, buffer, recv_size);
		if(-1 == ret){
			printf("recv http req error:%m\n");
			return -1;
		}
		buffer[ret] = '\0';
		printf("recv:\n%s\n", buffer);

		char* rep = getHtml();
		ret = write(cfd, rep, strlen(rep));
		if( -1 == ret){
			printf("send data error:%m\n");
			free(rep);
			return -1;
		}
		free(rep);
		rep = NULL;
		printf("send data ok!\n");
		close(cfd);
	}
	close(sfd);

	return 0;
}

/*
	返回的内容为动态分配的内存，需要使用者释放
*/
char* getHtml(){
	//const char* model = "HTTP/1.0 200 OK\r\nContent_type:text/html\r\nContent-Length:%d\r\n\n%s";
	const char* model = "HTTP/1.0 200 OK\r\nContent_type:text/html\r\n\r\n%s";

	//读取文件内容
	int fd = open("index.html", O_RDONLY, 0);
	struct stat file_stat;
	int ret = fstat(fd, &file_stat);
	if(-1 == ret){
		printf("get file stat error:%m\n");
		exit(-1);
	}

	int file_size = file_stat.st_size + 1;
	char* file_contect = (char*)malloc(file_size);
	memset(file_contect, 0, file_size);
	ret = read(fd, file_contect, file_size);
	if(-1 == ret){
		printf("read file error:%m\n");
		exit(-1);
	}
	file_contect[file_size] = '\0';

	//组装响应报文
	int req_size = strlen(model) + file_size;
	char* rep = (char*)malloc(req_size);
	snprintf(rep, req_size, model, file_contect);
	free(file_contect);

	return rep;
}